/**
 * Copyright 2008-2009 HAN.BIFANG
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package han.bifang.business.domain;

import han.bifang.business.dao.BusBindingDao;
import han.bifang.business.dao.BusServiceRelDao;
import han.bifang.business.dao.DomainDao;
import han.bifang.business.dao.ServiceBindingDao;
import han.bifang.business.dao.ServiceBusDao;
import han.bifang.business.dao.ServiceDao;
import han.bifang.business.dao.ServiceQosDao;
import han.bifang.business.dao.ServiceVersionDao;
import han.bifang.business.dao.StatBusDao;
import han.bifang.business.dao.TreeDao;
import han.bifang.business.dao.VersionQosDao;
import han.bifang.business.sync.SyncUtils;
import han.bifang.common.entity.BusBindingWrapper;
import han.bifang.common.entity.EntityConstants;
import han.bifang.common.entity.SoaBusDetail;
import han.bifang.common.entity.SoaBusInnerService;
import han.bifang.common.entity.SoaBusServiceRel;
import han.bifang.common.entity.SoaBusServiceRelPK;
import han.bifang.common.entity.SoaDomain;
import han.bifang.common.entity.SoaJmsBinding;
import han.bifang.common.entity.SoaJmsBindingWrapper;
import han.bifang.common.entity.SoaNormalJms;
import han.bifang.common.entity.SoaService;
import han.bifang.common.entity.SoaServiceBus;
import han.bifang.common.entity.SoaServiceQos;
import han.bifang.common.entity.SoaServiceVersion;
import han.bifang.common.entity.SoaSoapBinding;
import han.bifang.common.entity.SoaStatBus;
import han.bifang.common.entity.SoaTreeUnit;
import han.bifang.common.entity.SoaVersionQos;
import han.bifang.common.exception.BifangErrorCode;
import han.bifang.common.exception.BifangException;
import han.bifang.common.utils.BifangConstants;
import han.bifang.common.utils.CommonUtils;

import java.util.ArrayList;
import java.util.List;

import com.sun.corba.se.impl.orbutil.concurrent.SyncUtil;

public class ServiceBusManager {

	public static ArrayList<String> createServiceBus(SoaTreeUnit t,
			SoaServiceBus b, ArrayList busBindings) throws BifangException {
		try {
			ArrayList<String> ret = new ArrayList<String>();
			;
			TreeDao.createTreeUnit(t);
			b.setUnitId(t.getId());
			ServiceBusDao.createServiceBus(b);
			t.setKey(b.getId());
			TreeDao.modifyTreeUnit(t);
			ret.add(t.getId());
			ret.add(b.getId());
			String url = null, httpUrl = null;
			for (int i = 0, j = busBindings.size(); i < j; i++) {
				BusBindingWrapper cbw = (BusBindingWrapper) busBindings.get(i);
				cbw.getBusBinding().setBusId(b.getId());
				if (cbw.getBusBinding().getType().equals(
						EntityConstants.BINDING_HTTP)) {
					BusBindingDao.createBinding(cbw.getBusBinding(), cbw
							.getHttpBinding());
					if (cbw.getBusBinding().getName().equals(
							EntityConstants.BUS_BINDING_HTTP)) {
						httpUrl = cbw.getHttpBinding().getUrl();
					}

				} else if (cbw.getBusBinding().getType().equals(
						EntityConstants.BINDING_JMS)) {
					BusBindingDao.createBinding(cbw.getBusBinding(), cbw
							.getJmsBinding());
					url = ((SoaNormalJms) cbw.getJmsBinding().getInfo())
							.getServerUrl();
				} else if (cbw.getBusBinding().getType().equals(
						EntityConstants.BINDING_SOAP)) {
					BusBindingDao.createBinding(cbw.getBusBinding(), cbw
							.getSoapBinding());
				} else if (cbw.getBusBinding().getType().equals(
						EntityConstants.BINDING_WEB_SERVICES)) {
					BusBindingDao.createBinding(cbw.getBusBinding(), cbw
							.getSoapBinding());
				}

			}
			int index = httpUrl.lastIndexOf("gateway/v1/http");
			httpUrl = httpUrl.substring(0, index);
			// create service
			SoaService s = new SoaService();
			s.setCreateTime(CommonUtils.getNowStr());
			s.setDefaultVersion("1.0");
			s.setServiceCode(b.getCode() + ".notify");
			s.setServiceName(b.getCode() + ".notify");
			s.setStatus(EntityConstants.SERVICE_STATUS_PUBLISHED);
			s.setDescription("Notify Service of Service Bus " + b.getName());
			s.setBusId(b.getId());

			ServiceDao.createService(s);

			SoaBusServiceRel rel = new SoaBusServiceRel();
			SoaBusServiceRelPK pk = new SoaBusServiceRelPK();
			pk.setBusId(b.getId());
			pk.setServiceId(s.getId());
			rel.setCompId(pk);
			BusServiceRelDao.createBusServiceRef(rel);

			ArrayList<SoaServiceQos> sql = new ArrayList<SoaServiceQos>();
			SoaServiceQos sq = new SoaServiceQos();
			sq.setName(EntityConstants.QOS_ACL);
			sq.setValue(EntityConstants.QOS_NO);
			sq.setServiceId(s.getId());
			sql.add(sq);

			sq = new SoaServiceQos();
			sq.setName(EntityConstants.QOS_LOG);
			sq.setValue(EntityConstants.QOS_NO);
			sq.setServiceId(s.getId());
			sql.add(sq);

			sq = new SoaServiceQos();
			sq.setName(EntityConstants.QOS_RETRY);
			sq.setValue(EntityConstants.QOS_YES);
			sq.setServiceId(s.getId());
			sql.add(sq);

			ServiceQosDao.createServiceQos(sql);

			SoaServiceVersion v = new SoaServiceVersion();
			v.setBindingType(EntityConstants.BINDING_JMS);
			v.setDefault(true);
			v.setPublishTime(CommonUtils.getNowStr());
			v.setDescription("version 1");
			v.setServiceCode(s.getServiceCode());
			v.setServiceId(s.getId());
			v.setStatus(EntityConstants.SERVICE_STATUS_PUBLISHED);
			v.setVersion("1.0");

			SoaJmsBinding jms = new SoaJmsBinding();
			jms.setJmsType(EntityConstants.JMS_TYPE_QUEUE);
			jms.setServer(b.getAppServer());
			jms.setServerVersion(b.getServerVersion());

			SoaNormalJms info = new SoaNormalJms();
			info.setServerUrl(url);
			info.setDestinationJndi(BifangConstants.BUS_NOTIFY_QUEUE);
			info.setFactoryUrl(BifangConstants.BUS_NOTIFY_FAC);

			SoaJmsBindingWrapper jbw = new SoaJmsBindingWrapper();
			jbw.setInfo(info);
			jbw.setJmsBinding(jms);
			ServiceBindingDao.createBinding(jbw);
			// sb.setUrl(url + "services/notify");

			ServiceBindingDao.createBinding(jms);
			v.setBindingId(jms.getId());
			ServiceVersionDao.createVersion(v);

			ArrayList<SoaVersionQos> vql = new ArrayList<SoaVersionQos>();
			SoaVersionQos vq = new SoaVersionQos();
			vq.setName(EntityConstants.QOS_COMM_TYPE);
			vq.setValue(EntityConstants.ASYNC);
			vq.setVersionId(v.getId());
			vql.add(vq);

			vq = new SoaVersionQos();
			vq.setName(EntityConstants.QOS_LOG);
			vq.setValue(EntityConstants.QOS_NO);
			vq.setVersionId(v.getId());
			vql.add(vq);

			vq = new SoaVersionQos();
			vq.setName(EntityConstants.QOS_RETRY);
			vq.setValue(EntityConstants.QOS_YES);
			vq.setVersionId(v.getId());
			vql.add(vq);

			VersionQosDao.createVersionQos(vql);

			// create getResult service
			s = new SoaService();
			s.setCreateTime(CommonUtils.getNowStr());
			s.setDefaultVersion("1.0");
			s.setServiceCode(b.getCode() + ".getResult");
			s.setServiceName(b.getCode() + ".getResult");
			s.setStatus(EntityConstants.SERVICE_STATUS_PUBLISHED);
			s.setDescription("GetResult Service of Service Bus " + b.getName());
			s.setBusId(b.getId());

			ServiceDao.createService(s);

			rel = new SoaBusServiceRel();
			pk = new SoaBusServiceRelPK();
			pk.setBusId(b.getId());
			pk.setServiceId(s.getId());
			rel.setCompId(pk);

			BusServiceRelDao.createBusServiceRef(rel);
			sql = new ArrayList<SoaServiceQos>();
			sq = new SoaServiceQos();
			sq.setName(EntityConstants.QOS_ACL);
			sq.setValue(EntityConstants.QOS_NO);
			sq.setServiceId(s.getId());
			sql.add(sq);

			sq = new SoaServiceQos();
			sq.setName(EntityConstants.QOS_LOG);
			sq.setValue(EntityConstants.QOS_NO);
			sq.setServiceId(s.getId());
			sql.add(sq);

			sq = new SoaServiceQos();
			sq.setName(EntityConstants.QOS_RETRY);
			sq.setValue(EntityConstants.QOS_YES);
			sq.setServiceId(s.getId());
			sql.add(sq);

			ServiceQosDao.createServiceQos(sql);

			v = new SoaServiceVersion();
			v.setBindingType(EntityConstants.BINDING_SOAP);
			v.setDefault(true);
			v.setPublishTime(CommonUtils.getNowStr());
			v.setDescription("version 1");
			v.setServiceCode(s.getServiceCode());
			v.setServiceId(s.getId());
			v.setStatus(EntityConstants.SERVICE_STATUS_PUBLISHED);
			v.setVersion("1.0");

			SoaSoapBinding sb = new SoaSoapBinding();
			sb.setUrl(httpUrl + "services/v1/getResult");
			sb.setSoapVersion("1.1");

			ServiceBindingDao.createBinding(sb);
			v.setBindingId(sb.getId());
			ServiceVersionDao.createVersion(v);

			vql = new ArrayList<SoaVersionQos>();
			vq = new SoaVersionQos();
			vq.setName(EntityConstants.QOS_COMM_TYPE);
			vq.setValue(EntityConstants.SYNC);
			vq.setVersionId(v.getId());
			vql.add(vq);

			vq = new SoaVersionQos();
			vq.setName(EntityConstants.QOS_LOG);
			vq.setValue(EntityConstants.QOS_NO);
			vq.setVersionId(v.getId());
			vql.add(vq);

			vq = new SoaVersionQos();
			vq.setName(EntityConstants.QOS_RETRY);
			vq.setValue(EntityConstants.QOS_YES);
			vq.setVersionId(v.getId());
			vql.add(vq);

			VersionQosDao.createVersionQos(vql);

			// create stat record
			SoaDomain d = DomainDao.getDomain(b.getDomainId());
			if (d.getLocal()) {
				SoaStatBus ssb = new SoaStatBus();
				ssb.setBusCode(b.getCode());
				ssb.setBusId(b.getId());
				ssb
						.setStatBeginTime(String.valueOf(System
								.currentTimeMillis()));
				//ssb.setFailRequest(0);
				ssb.setSuccessRequest(0);
				ssb.setTotalRequest(0);

				StatBusDao.createStatBus(ssb);
			}
			return ret;
		} catch (BifangException e) {
			throw e;

		}

	}

	public static void modifyServiceBus(SoaServiceBus b, ArrayList bindings)
			throws BifangException {
		try {
			ServiceBusDao.modifyServiceBus(b);
			SoaTreeUnit t = TreeDao.getTreeUnit(b.getUnitId());
			t.setName(b.getName());
			TreeDao.modifyTreeUnit(t);
			if (bindings.size() > 0) {
				BusBindingDao.removeBindingByBusId(b.getId());

				String url = null, jmsServerUrl = null;
				for (int i = 0, j = bindings.size(); i < j; i++) {
					BusBindingWrapper cbw = (BusBindingWrapper) bindings.get(i);
					cbw.getBusBinding().setBusId(b.getId());
					if (cbw.getBusBinding().getType().equals(
							EntityConstants.BINDING_HTTP)) {
						BusBindingDao.createBinding(cbw.getBusBinding(), cbw
								.getHttpBinding());
						if (cbw.getBusBinding().getName().equals(
								EntityConstants.BUS_BINDING_HTTP)) {
							url = cbw.getHttpBinding().getUrl();
						}
					} else if (cbw.getBusBinding().getType().equals(
							EntityConstants.BINDING_JMS)) {
						BusBindingDao.createBinding(cbw.getBusBinding(), cbw
								.getJmsBinding());
						jmsServerUrl = ((SoaNormalJms) cbw.getJmsBinding()
								.getInfo()).getServerUrl();
					} else if (cbw.getBusBinding().getType().equals(
							EntityConstants.BINDING_SOAP)) {
						BusBindingDao.createBinding(cbw.getBusBinding(), cbw
								.getSoapBinding());
					} else if (cbw.getBusBinding().getType().equals(
							EntityConstants.BINDING_WEB_SERVICES)) {
						BusBindingDao.createBinding(cbw.getBusBinding(), cbw
								.getSoapBinding());
					}

				}
				int index = url.lastIndexOf("gateway/v1/http");
				url = url.substring(0, index);

				SoaBusInnerService[] in = ServiceBusDao.getInnerServices(b
						.getId());
				((SoaNormalJms) in[0].getJmsBinding().getInfo())
						.setServerUrl(jmsServerUrl);
				ServiceBindingDao.modifyBinding(in[0].getJmsBinding());

				in[1].getSoapBinding().setUrl(url + "services/v1/getResult");
				ServiceBindingDao.modifyBinding(in[1].getSoapBinding());

			}
			SyncUtils.sync(SyncUtils.SERVICE_BUS, b.getId());
		} catch (BifangException e) {
			throw e;

		}

	}

	public static void removeServiceBus(String serviceBusId)
			throws BifangException {
		try {
			if (ServiceBusDao.hasBindedServices(serviceBusId))
				throw new BifangException(
						BifangErrorCode.SERVICE_BUS_HAS_BINDED_SERVICES_ERROR,
						"ServiceBus[id=" + serviceBusId
								+ "] has binded serivces");
			SoaServiceBus b = ServiceBusDao.getServiceBus(serviceBusId);

			TreeDao.removeTreeUnit(b.getUnitId());
			BusBindingDao.removeBindingByBusId(serviceBusId);

			ServiceBusDao.removeInnerServices(serviceBusId);

			ServiceBusDao.removeServiceBus(b);
			SoaDomain d = DomainDao.getDomain(b.getDomainId());
			if (d.getLocal()) {
				StatBusDao.removeStatBus(b.getCode());
			}
			SyncUtils.sync(SyncUtils.SERVICE_BUS, b.getId());
		} catch (BifangException e) {
			throw e;

		}

	}

	public static List getServiceBusByDomainId(String id)
			throws BifangException {
		try {

			return ServiceBusDao.getServiceBusByDomainId(id);

		} catch (BifangException e) {
			throw e;

		}

	}

	public static SoaBusDetail getServiceBusDetail(String id)
			throws BifangException {
		try {
			SoaBusDetail ret = new SoaBusDetail();

			ret.setServiceBus(ServiceBusDao.getServiceBus(id));
			ret.setBindings(BusBindingDao.getBusBindings(id));
			SoaBusInnerService[] in = ServiceBusDao.getInnerServices(id);
			ret.setNotifyService(in[0]);
			ret.setGetResultService(in[1]);
			return ret;

		} catch (BifangException e) {
			throw e;

		}

	}

	public static List getLocalServiceBus() throws BifangException {
		try {
			SoaDomain d = DomainDao.getLocalDomain();
			if (d == null)
				return new ArrayList();

			return getServiceBusByDomainId(d.getId());

		} catch (BifangException e) {
			throw e;

		}
	}
	
	

}
